﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Utils.Collections
{
    public class Pool<ItemType> where ItemType : class, new()
    {

        /// <summary>Default number of recyclable objects the pool will store</summary>
        public const int DefaultPoolSize = 32;

        public Pool() : this(DefaultPoolSize) { }

        public Pool(int startCapacity)
        {
            items = new List<ItemType>(startCapacity);
        }

        public ItemType Get()
        {
            lock (this)
            {
                if (this.items.Count > 0)
                {
                    ItemType item = items[items.Count - 1];
                    items.RemoveAt(items.Count - 1);
                    return item;
                }
                else
                {
                    return new ItemType();
                }
            }
        }

        public void Redeem(ItemType item)
        {
            // Call Recycle() when the object is redeemed (instead of when it leaves
            // the pool again) in order to eliminate any references the object may hold
            // to other objects.
            callRecycleIfSupported(item);

            lock (this)
            {
                this.items.Add(item);
            }
        }

        private static void callRecycleIfSupported(ItemType item)
        {
            IRecyclable recycleable = item as IRecyclable;
            if (recycleable != null)
            {
                recycleable.Recycle();
            }
        }

        private List<ItemType> items;
    }
}
